iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0

這一篇要來介紹怎麼使用 Jest + Testing Library 來測試路徑,我是使用 React Router 來做路徑管理。

這邊我分兩個部分,一個是 router config 的導頁測試,一個是 navbar 的路徑測試。

Router 導頁測試

router config 的結構會是長這樣:

import { FormPage } from "@/pages/FormPage";
import { HomePage } from "@/pages/HomePage";
import { Home } from "@/pages/HomePage/Home";
import { Navigate } from "react-router-dom";

export const routerConfig = [
  {
    path: "/",
    element: <Navigate to='/home' />,
  },
  {
    path: "home",
    element: <HomePage />,
    children: [
      { index: true, element: <Home /> },
      {
        path: "form",
        element: <FormPage />,
      },
    ],
  },
];

要測 router config 測試的是對應路徑是否有顯示正確的 component,這邊使用 jest.mock 去模擬元件,就可以避免當元件內容改變時,測試也要重寫的問題,所以導頁測試其實就是在測試路由是否有對應到正確的元件路徑

測試案例描述:

describe("router testing", () => {
  it("當 router 路徑為 '/home' 顯示 'home page' 文字", () => {});
  it("當 router 路徑為 '/home/form' 顯示 'form page' 文字", () => {});
});

完整測試:

import { render, screen } from "@testing-library/react";
import { RouterProvider, createMemoryRouter } from "react-router-dom";
import { routerConfig } from ".";

// 模擬元件回傳
jest.mock("@/pages/HomePage/Home/index.tsx", () => {
  return {
    Home: () => <div>home page</div>,
  };
});

jest.mock("@/pages/FormPage/index.tsx", () => {
  return {
    FormPage: () => <div>form Page</div>,
  };
});

// 測試
describe("router testing", () => {
  it("當 router 路徑為 '/home' 顯示 'home page' 文字", () => {
    const router = createMemoryRouter(routerConfig, {
      initialEntries: ["/home"],
    });

    render(<RouterProvider router={router} />);

    expect(screen.getByText(/home page/i)).toBeInTheDocument();
  });

  it("當 router 路徑為 '/home/form' 顯示 'form page' 文字", () => {
    const router = createMemoryRouter(routerConfig, {
      initialEntries: ["/home/form"],
    });

    render(<RouterProvider router={router} />);

    expect(screen.getByText(/form page/i)).toBeInTheDocument();
  });
});

可以看到每個測試案例都有一個 router 的初始化及渲染元件,重複的地方我會提出來寫一個 function

const renderRouter = (path: string) => {
  const router = createMemoryRouter(routerConfig, {
    initialEntries: [path],
  });

  render(<RouterProvider router={router} />);
};

這樣就可以讓測試碼更簡潔。

describe("router testing", () => {
  it("當 router 路徑為 '/home' 顯示 'home page' 文字", () => {
    renderRouter("/home");

    expect(screen.getByText(/home page/i)).toBeInTheDocument();
  });

  it("當 router 路徑為 '/home/form' 顯示 'form page' 文字", () => {
    renderRouter("/home/form");

    expect(screen.getByText(/form page/i)).toBeInTheDocument();
  });
});

不過優化測試碼的部分,就算沒做也無傷大雅,尤其是時程很趕時,有寫測試就已經很不錯了哈哈。

Navbar 路徑測試

那在 navbar 的路徑測試,測試的是點擊 navbar 的連結,是否有導頁到正確的路徑。

測試案例描述:

describe("navbar testing", () => {
  it("點擊 'home' 連結,網址導頁到 '/home' 路徑", () => {});
  it("點擊 'form' 連結,網址導頁到 '/home/form' 路徑", () => {});
});

需要引入 history 套件來模擬路由的行為,並使用 history.location.pathname 來取得當前路徑。

npm install --save-dev history

完整測試:

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MemoryHistory, createMemoryHistory } from "history";
import { Router } from "react-router-dom";
import { Navbar } from ".";

describe("navbar testing", () => {
  let history: MemoryHistory;
  const user = userEvent.setup();
  beforeEach(() => {
    history = createMemoryHistory();
    render(
      <Router location='/home' navigator={history}>
        <Navbar />
      </Router>
    );
  });

  it("點擊 'home' 連結,網址導頁到 '/home' 路徑", async () => {
    const homeLink = screen.getByText(/home/i);
    expect(homeLink).toBeInTheDocument();
    await user.click(homeLink);
    expect(history.location.pathname).toBe("/home");
  });

  it("點擊 'form' 連結,網址導頁到 '/home/form' 路徑", async () => {
    const button = screen.getByText(/form/i);
    await user.click(button);
    expect(history.location.pathname).toBe("/home/form");
  });
});

結論

可以看到我把點擊連結的行為分成兩個部分來測試

  • 測試元件是否顯示正確
  • 試點擊連結網址是否正確

這樣的好處是能讓測試項目更加單純,也能更快速的找到問題。


上一篇
[Day 09] React + Jest 表單驗證測試 (AI)
下一篇
[Day 11] React + Jest 路徑測試 (AI)
系列文
React 測試 x AI:探索測試新境界,測試不再枯燥乏味!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言